package com.sen.gulimall.order.listener;

import com.rabbitmq.client.Channel;
import com.sen.common.constant.OrderCacheConst;
import com.sen.common.constant.OrderConstant;
import com.sen.common.to.mq.SeckillOrderTo;
import com.sen.gulimall.order.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author Kisen
 * @email lqs0911@qq.com
 * @date 2023/2/3 11:54
 * @detail
 */
@Slf4j
@Service
@RabbitListener(queues = OrderConstant.ORDER_SECKILL_ORDER_QUEUE)
public class OrderSeckillListener {


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private OrderService orderService;

    @RabbitHandler
    public void listenOrderSeckillOrderQueue(SeckillOrderTo seckillOrder, Message message, Channel channel) throws IOException {
        String messageId = message.getMessageProperties().getHeader("spring_returned_message_correlation");
        log.info("队列{}已经接收到id为{}的消息：{}", OrderConstant.ORDER_SECKILL_ORDER_QUEUE, messageId, seckillOrder);

        try {
            String fullKey = OrderCacheConst.ORDER_SECKILL_ORDER_KEY + messageId;
            Boolean flag = redisTemplate.hasKey(fullKey);
            //redis中不存在，则说明消息没有消费过，按正常业务处理；否则，直接跳过
            if (!flag) {

                log.info("准备创建秒杀单的详细信息...");
                orderService.createSeckillOrder(seckillOrder);

                //存入redis
                redisTemplate.opsForValue().setIfAbsent(fullKey, fullKey, OrderCacheConst.MQ_MESSAGE_ID_CACHE_TIMEOUT_DAYS, TimeUnit.DAYS);
            }

            //TODO:记录消息日志：消费成功
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        } catch (Exception e) {
            //业务异常，不重回队列，而是放入死信队列处理
            log.error("队列{}接收到id为{}的消息：{}，处理业务异常：{}", OrderConstant.ORDER_SECKILL_ORDER_QUEUE, messageId, seckillOrder, e);

            //TODO:记录消息日志：消费失败
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }
}
